/**
 * @file ecc.h
 * @brief This header file contains declarations and documentation for elliptic curve cryptography operations.
 *
 * Constants:
 * - sm2: A constant representing the SM2 elliptic curve.
 * - fpt: An array of constants representing finite field points.
 *
 * Functions:
 * - point_fm_fp(): Initializes a point from finite field coordinates.
 * - point_fm_str(): Initializes a point from string coordinates.
 * - point_fm_byt(): Initializes a point from byte coordinates.
 * - point_fm_jpoint(): Initializes a point from a jpoint.
 * - point_fm_compress_octets(): Initializes a point from compressed octets.
 * - point_fm_octets(): Initializes a point from octets.
 * - point_fm_der(): Initializes a point from DER-encoded data.
 * - point_to_compress_octets(): Converts a point to compressed octets.
 * - point_to_uncompressed_octets(): Converts a point to uncompressed octets.
 * - point_to_mix_octets(): Converts a point to mixed octets.
 * - point_to_der(): Converts a point to DER format.
 * - point_is_on_curve(): Checks if a point is on the curve.
 * - point_to_jpoint(): Converts a point to a jpoint.
 * - point_mul(): Multiplies a point by a finite field integer.
 * - point_mutmul(): Multiplies two points by finite field integers and adds the results.
 * - point_mul_fixed(): Multiplies a fixed point by a finite field integer.
 * - jpoint_set(): Sets the coordinates of a jpoint.
 * - jpoint_neg(): Negates a jpoint.
 * - jpoint_add(): Adds two jpoints.
 * - jpoint_sub(): Subtracts one jpoint from another.
 * - jpoint_dou(): Doubles a jpoint.
 * - jpoint_mdo(): Performs repeated doublings of a jpoint.
 * - jpoint_mul(): Multiplies a jpoint by a finite field integer.
 * - jpoint_mul_fixed(): Multiplies a fixed jpoint by a finite field integer.
 * - jpoint_copy(): Copies the coordinates of one jpoint to another.
 * - jpoint_set_infinity(): Sets a jpoint to infinity.
 * - jpoint_is_at_infinity(): Checks if a jpoint is at infinity.
 */

#ifndef SM_ECC_H
#define SM_ECC_H

#include "fp.h"

extern const curve sm2;

/**
 * @brief Initializes a point from finite field coordinates.
 * @param p The point object to be initialized.
 * @param x The x-coordinate in the finite field.
 * @param y The y-coordinate in the finite field.
 */
void point_fm_fp(point *p, const fp x, const fp y);

/**
 * @brief Initializes a point from string coordinates.
 * @param p The point object to be initialized.
 * @param x The x-coordinate as a string.
 * @param y The y-coordinate as a string.
 */
void point_fm_str(point *p, const str x, const str y);

/**
 * @brief Initializes a point from byte coordinates.
 * @param p The point object to be initialized.
 * @param x The x-coordinate as a byte.
 * @param y The y-coordinate as a byte.
 */
void point_fm_byt(point *p, const byt x, const byt y);

/**
 * @brief Initializes a point from a jpoint.
 * @param p The point object to be initialized.
 * @param a The jpoint to initialize from.
 */
void point_fm_jpoint(point *p, const jpoint *a);

/**
 * @brief Initializes a point from compressed octets.
 * @param p The point object to be initialized.
 * @param src The compressed octets representation of the point.
 */
void point_fm_compress_octets(point *p, const u8 *src);

/**
 * @brief Initializes a point from octets.
 * @param p The point object to be initialized.
 * @param in The octets representation of the point.
 */
void point_fm_octets(point *p, const u8 *in);

/**
 * @brief Initializes a point from DER-encoded data.
 * @param p The point object to be initialized.
 * @param src The DER-encoded data representing the point.
 */
void point_fm_der(point *p, const u8 **src, u64 *slen);

/**
 * @brief Converts a point to compressed octets.
 * @param p The point to be converted.
 * @param out The output buffer to store the compressed octets.
 */
void point_to_compress_octets(point *p, u8 out[33]);

/**
 * @brief Converts a point to uncompressed octets.
 * @param p The point to be converted.
 * @param out The output buffer to store the uncompressed octets.
 */
void point_to_uncompressed_octets(point *p, u8 out[65]);

/**
 * @brief Converts a point to mixed octets.
 * @param p The point to be converted.
 * @param out The output buffer to store the mixed octets.
 */
void point_to_mix_octets(point *p, u8 out[65]);

/**
 * @brief Converts a point to DER format.
 * @param p The point to be converted.
 * @param dst The output buffer to store the DER-encoded data.
 * @param dlen The length of the DER-encoded data.
 */
void point_to_der(point *p, u8 **dst, u64 *dlen);

/**
 * @brief Checks if a point is on the curve.
 * @param r The point to check.
 * @return 1 if the point is on the curve, 0 otherwise.
 */
int point_is_on_curve(point *r);

/**
 * @brief Converts a point to a jpoint.
 * @param r The jpoint to be set.
 * @param p The point to be converted.
 */
void point_to_jpoint(jpoint *r, const point *p);

/**
 * @brief Multiplies a point by a finite field integer.
 * r = [k]p
 * @param p The point to be multiplied.
 * @param k The finite field integer.
 * @param a The point to multiply.
 */
void point_mul(point *r, fp k, const point *p);

/**
 * @brief Multiplies two points by finite field integers and adds the results.
 * r = [s]p + [t}q
 * @param r The point to store the result.
 * @param s The first finite field integer.
 * @param t The second finite field integer.
 * @param q The second point to multiply.
 */
void point_mutmul(point *r, fp s, fp t, const point *q);

/**
 * @brief Multiplies a fixed point by a finite field integer.
 * @param r The point to store the result.
 * @param k The fixed integer.
 */
void point_mul_fixed(point *r, fp k);

/**
 * @brief Sets the coordinates of a jpoint.
 * @param p The jpoint to be set.
 * @param x The x-coordinate.
 * @param y The y-coordinate.
 * @param z The z-coordinate.
 */
void jpoint_set(jpoint *p, const fp x, const fp y, const fp z);

/**
 * @brief Adds two jpoints.
 * @param r The sum of the jpoints.
 * @param a The first jpoint.
 * @param b The second jpoint.
 */
void jpoint_add(jpoint *r, const jpoint *a, const jpoint *b);

/**
 * @brief Subtracts one jpoint from another.
 * @param r The difference of the jpoints.
 * @param p The jpoint to subtract from.
 * @param q The jpoint to subtract.
 */
void jpoint_sub(jpoint *r, const jpoint *p, const jpoint *q);

/**
 * @brief Point doubling, Jacobian coordinates.
 * @param r The doubled jpoint.
 * @param a The jpoint to be doubled.
 */
void jpoint_dou(jpoint *r, const jpoint *a);

/**
 * @brief Performs repeated doublings of a jpoint.
 * r = [2^m]p
 * @param r The result of repeated doublings.
 * @param m The number of doublings.
 * @param p The jpoint to be doubled.
 */
void jpoint_mdo(jpoint *r, u32 m, const jpoint *p);

/**
 * @brief Multiplies a jpoint by a finite field integer.
 * r = [k]g
 * @param r The result of the multiplication.
 * @param k The finite field integer.
 * @param g The jpoint to be multiplied.
 */
void jpoint_mul(jpoint *r, fp k, const jpoint *g);

/**
 * @brief Multiplies a fixed jpoint by a finite field integer.
 * @param r The result of the multiplication.
 * @param k The fixed integer.
 */
void jpoint_mul_fixed(jpoint *r, fp k);

/**
 * @brief Point addition, affine-Jacobian coordinates
 * @param r The result of the addition.
 * @param p The first jpoint.
 * @param q The second point.
 */
void jpoint_add_AJ(jpoint *r, const jpoint *p, const point *q);

/**
 * @brief Point subtraction, affine-Jacobian coordinates
 * @param r The result of the subtraction.
 * @param p The first jpoint.
 * @param q The second point.
 */
void jpoint_sub_AJ(jpoint *r, const jpoint *p, const point *q);

/**
 * @brief Copies the coordinates of one jpoint to another.
 * @param r The destination jpoint.
 * @param p The source jpoint.
 */
#define jpoint_copy(r, p) jpoint_set(r, p->x, p->y, p->z)

/**
 * @brief Sets a jpoint to infinity.
 * @param r The jpoint to be set.
 */
#define jpoint_set_infinity(r) jpoint_set(r, one, one, zero)

/**
 * @brief Checks if a jpoint is at infinity.
 * @param r The jpoint to check.
 * @return 1 if the jpoint is at infinity, 0 otherwise.
 */
#define jpoint_is_at_infinity(r) fp_equ(r->z, zero)

#endif // SM_ECC_H